/*
 * Copyright 1999-2018 Alibaba Group Holding Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.alibaba.csp.sentinel.demo.apache.dubbo;

import java.util.List;

import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import com.alibaba.csp.sentinel.datasource.ReadableDataSource;
import com.alibaba.csp.sentinel.datasource.zookeeper.ZookeeperDataSource;
import com.alibaba.csp.sentinel.demo.apache.dubbo.provider.ProviderConfiguration;
import com.alibaba.csp.sentinel.init.InitExecutor;
import com.alibaba.csp.sentinel.property.SentinelProperty;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;

/**
 * Provider demo for Apache Dubbo 2.7.x or above. Please add the following VM arguments:
 * <pre>
 * -Djava.net.preferIPv4Stack=true
 * -Dcsp.sentinel.api.port=8720
 * -Dproject.name=dubbo-provider-demo
 * </pre>
 *
 * @author Eric Zhao
 */
public class FooProviderBootstrap {

//    private static final String INTERFACE_RES_KEY = FooService.class.getName();
//    private static final String RES_KEY = INTERFACE_RES_KEY + ":sayHello(java.lang.String)";

    public static void main(String[] args) {
        // Users don't need to manually call this method.
        // Only for eager initialization.
        InitExecutor.doInit();

        try {
			initFlowRule();
		} catch (Exception e) {
			//zk 异常或者是获取数据异常
			e.printStackTrace();
		}

        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
        context.register(ProviderConfiguration.class);
        context.refresh();

        System.out.println("Service provider is ready");
    }

/*    private static void initFlowRule() {
        FlowRule flowRule = new FlowRule(INTERFACE_RES_KEY)
            .setCount(10)
            .setGrade(RuleConstant.FLOW_GRADE_QPS);
        FlowRuleManager.loadRules(Collections.singletonList(flowRule));

        final String remoteAddress = "127.0.0.1:2181";
        // 引入groupId和dataId的概念，是为了方便和Nacos进行切换
//        final String groupId = "Sentinel-Demo";
        final String groupId = "sentinel_datasource_zk";
        
//        final String flowDataId = "SYSTEM-CODE-DEMO-FLOW";
        final String flowDataId = "com.alibaba.csp.sentinel.demo.apache.dubbo.FooProviderBootstrap";
        // final String degradeDataId = "SYSTEM-CODE-DEMO-DEGRADE";
        // final String systemDataId = "SYSTEM-CODE-DEMO-SYSTEM";


        // 规则会持久化到zk的/groupId/flowDataId节点
        // groupId和和flowDataId可以用/开头也可以不用
        // 建议不用以/开头，目的是为了如果从Zookeeper切换到Nacos的话，只需要改数据源类名就可以
        ReadableDataSource<String, List<FlowRule>> flowRuleDataSource = new ZookeeperDataSource<>(remoteAddress, groupId, flowDataId,
                source -> JSON.parseObject(source, new TypeReference<List<FlowRule>>() {}));
        SentinelProperty<List<FlowRule>>  props = flowRuleDataSource.getProperty();
        FlowRuleManager.register2Property(props);
    }*/
    
    /**
     * 用该处代码替代上面的代码块
     * @throws Exception
     */
    private static void initFlowRule() throws Exception {
        //1.获取所有的应用节点
    	final String remoteAddress = "127.0.0.1:2181";
    	final String groupId = "sentinel_datasource_zk";
    	RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000,3);
		CuratorFramework client = CuratorFrameworkFactory.newClient(remoteAddress,retryPolicy);
		client.start();
		List<String> appids = client.getChildren().forPath("/sentinel_datasource_zk/"+groupId);
    	//2.循环添加到zk中
		if(appids != null){
			for(String appId : appids){
		        ReadableDataSource<String, List<FlowRule>> flowRuleDataSource = new ZookeeperDataSource<>(remoteAddress, groupId, appId,
		                source -> JSON.parseObject(source, new TypeReference<List<FlowRule>>() {}));
		        SentinelProperty<List<FlowRule>>  props = flowRuleDataSource.getProperty();
		        FlowRuleManager.register2Property(props);
			}
		}
    }
}
